#ifndef RTREACTORINTERFACE_H
#define RTREACTORINTERFACE_H

#if defined  (RT_LINUX)
  #define RT_ENABLE_CALENDAR_TIMER
#endif 

#include "RtDefines.h"
#include "RtThreadInterface.h"

class CRtTimeValue;
class CRtInetAddr;

/*
#ifdef RT_LINUX
const DWORD g_dwDefaultTimerTickInterval = 10; // 10ms
#else
*/
const DWORD g_dwDefaultTimerTickInterval = 30; // 30ms
//#endif

/**
 * @class IRtEventHandler
 *
 * @brief Provides an abstract interface for handling various types of I/O events.
 *
 * Subclasses read/write input/output on an I/O descriptor(implemented),
 * handle an exception raised on an I/O descriptor(not implemented yet)
 * 
 */
class RT_API_EXPORT IRtEventHandler
{
public:
	typedef long MASK;
	enum {
		NULL_MASK = 0,
		ACCEPT_MASK = (1 << 0),
		CONNECT_MASK = (1 << 1),
		READ_MASK = (1 << 2),
		WRITE_MASK = (1 << 3),
		EXCEPT_MASK = (1 << 4),
		TIMER_MASK = (1 << 5),
		ALL_EVENTS_MASK = READ_MASK |
                      WRITE_MASK |
                      EXCEPT_MASK |
                      ACCEPT_MASK |
                      CONNECT_MASK |
                      TIMER_MASK,
		SHOULD_CALL = (1 << 6),
		CLOSE_MASK = (1 << 7),
		EVENTQUEUE_MASK = (1 << 8)
	};

	virtual RT_HANDLE GetHandle() const ;
	
	/// Called when input events occur (e.g., data is ready).
	/// OnClose() will be callbacked if return -1.
	virtual int OnInput(RT_HANDLE aFd = RT_INVALID_HANDLE);

	/// Called when output events are possible (e.g., when flow control
	/// abates or non-blocking connection completes).
	/// OnClose() will be callbacked if return -1.
	virtual int OnOutput(RT_HANDLE aFd = RT_INVALID_HANDLE);

	/// Called when an exceptional events occur (e.g., OOB data).
	/// OnClose() will be callbacked if return -1.
	/// Not implemented yet.
	virtual int OnException(RT_HANDLE aFd = RT_INVALID_HANDLE);

	/**
	 * Called when a <On*()> method returns -1 or when the
	 * <RemoveHandler> method is called on an <CReactor>.  The
	 * <aMask> indicates which event has triggered the
	 * <HandleClose> method callback on a particular <aFd>.
	 */
	virtual int OnClose(RT_HANDLE aFd, MASK aMask);
	
	virtual ~IRtEventHandler();
};

/**
 * @class IRtReactor
 *
 * @brief An abstract class for implementing the Reactor Pattern.
 * 
 */
class /*RT_API_EXPORT*/ IRtReactor : public IRtEventQueue, public IRtTimerQueue
{
public:
	/// Initialization.
	virtual RtResult Open() = 0;

	/**
	 * Register <aEh> with <aMask>.  The handle will always
	 * come from <GetHandle> on the <aEh>.
	 * If success:
	 *    if <aEh> is registered, return RT_ERROR_FOUND;
	 *    else return RT_OK;
	 */
	virtual RtResult RegisterHandler(
		IRtEventHandler *aEh,
		IRtEventHandler::MASK aMask) = 0;

	/**
	 * Removes <aEh> according to <aMask>. 
	 * If success:
	 *    if <aEh> is registered
	 *       If <aMask> equals or greater than that registered, return RT_OK;
	 *       else return RT_ERROR_FOUND;
	 *    else return RT_ERROR_NOT_FOUND;
	 */
	virtual RtResult RemoveHandler(
		IRtEventHandler *aEh,
		IRtEventHandler::MASK aMask = IRtEventHandler::ALL_EVENTS_MASK) = 0;

	virtual RtResult NotifyHandler(
		IRtEventHandler *aEh,
		IRtEventHandler::MASK aMask) = 0;

	virtual RtResult RunEventLoop() = 0;

	/// this function can be invoked in the different thread.
	virtual RtResult StopEventLoop() = 0;

	/// Close down and release all resources.
	virtual RtResult Close() = 0;

	typedef long PROPERTY;
	enum {
		NULL_PROPERTY = 0,
		SEND_REGISTER_PROPERTY = (1 << 0)
	};

	PROPERTY GetProperty()
	{
		return m_Property;
	}

	IRtReactor(PROPERTY aProperty) 
		: m_Property(aProperty)
	{
	}

	virtual ~IRtReactor();

protected:
	PROPERTY m_Property;
};

/**
 * @class IRtConnectorInternal
 *
 * @brief for internal connector, implement TCP, UDP, HTTP, SSL, etc.
 *
 */
class /*RT_API_EXPORT*/ IRtConnectorInternal
{
public:
	virtual int Connect(const CRtInetAddr &aAddr, CRtInetAddr *aAddrLocal = NULL) = 0;
	virtual int Close() = 0;

	virtual ~IRtConnectorInternal() { }
};

#endif // !RTREACTORINTERFACE_H
